package com.wg.core.properties;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 默认属性类
 *
 * @author 少爷123
 */
public class DefaultProperties extends BaseProperties {
    private static final Log log = LogFactory.get();
    private final Map<String, String> properties;

    public DefaultProperties(Map<String, String> properties) {
        this.properties = properties == null ? Collections.emptyMap() : properties;
    }

    @Override
    public String getStr(String key, String defaultValue) {
        String value = properties.get(key);
        return value != null ? value : defaultValue;
    }

    @Override
    public Integer getInt(String key, Integer defaultValue) {
        return Convert.toInt(getStr(key), defaultValue);
    }

    @Override
    public Long getLong(String key, Long defaultValue) {
        return Convert.toLong(getStr(key), defaultValue);
    }

    @Override
    public Boolean getBool(String key, Boolean defaultValue) {
        return Convert.toBool(getStr(key), defaultValue);
    }

    @Override
    public Float getFloat(String key, Float defaultValue) {
        return Convert.toFloat(getStr(key), defaultValue);
    }

    @Override
    public Double getDouble(String key, Double defaultValue) {
        return Convert.toDouble(getStr(key), defaultValue);
    }

    @Override
    public Short getShort(String key, Short defaultValue) {
        return Convert.toShort(getStr(key), defaultValue);
    }

    @Override
    public Byte getByte(String key, Byte defaultValue) {
        return Convert.toByte(getStr(key), defaultValue);
    }

    @Override
    public Date getDate(String key, Date defaultValue) {
        return Convert.toDate(getStr(key), defaultValue);
    }

    @Override
    public <E extends Enum<E>> E getEnum(Class<E> clazz, String key, E defaultValue) {
        return Convert.toEnum(clazz, getStr(key), defaultValue);
    }

    @Override
    public <E extends Enum<E>> E getEnum(Class<E> clazz, String key) {
        return getEnum(clazz, key, null);
    }

    @Override
    public <T> T toBean(Class<T> beanClass, String prefix) {
        if (!hasPropertiesWithPrefix(prefix)) {
            log.debug("No properties found for prefix: {}", prefix);
            return null;
        }

        try {
            T subObject = ReflectUtil.newInstance(beanClass);
            boolean fieldSet = false;

            for (Field subfield : ReflectUtil.getFields(beanClass)) {
                String subKey = prefix + "." + subfield.getName();
                if (properties.containsKey(subKey)) {
                    setFieldValue(subObject, subfield, subKey);
                    fieldSet = true;
                }
            }

            if (!fieldSet) {
                log.warn("No properties matched for bean: {} with prefix: {}",
                        beanClass.getSimpleName(), prefix);
            }
            return subObject;
        } catch (Exception e) {
            log.error("Failed to create bean instance for type: {} with prefix: {}",
                    beanClass.getName(), prefix, e);
            return null;
        }
    }

    @Override
    public <T> List<T> toList(Class<T> beanClass, String prefix) {
        return new ArrayList<>(toMap(beanClass, prefix).values());
    }

    @Override
    public <T> Map<String, T> toMap(Class<T> beanClass, String prefix) {
        Map<String, T> map = new HashMap<>();
        Set<String> processedKeys = new HashSet<>(); // 避免重复处理

        for (Map.Entry<String, String> entry : properties.entrySet()) {
            String key = entry.getKey();

            // 过滤非匹配前缀
            if (!key.startsWith(prefix)) continue;

            // 获取子路径（如：db.master.url -> 提取master）
            String suffix = key.substring(prefix.length());
            int dotIndex = suffix.indexOf('.');
            if (dotIndex <= 0) continue;

            String mapKey = suffix.substring(0, dotIndex);
            if (processedKeys.contains(mapKey)) continue;
            processedKeys.add(mapKey);

            // 构造完整子键
            String subKey = prefix + mapKey;
            T bean = toBean(beanClass, subKey);
            if (bean != null) {
                map.put(mapKey, bean);
            }
        }
        return map;
    }

    @Override
    public Set<String> getPropertyNames() {
        return Collections.unmodifiableSet(properties.keySet());
    }

    private boolean hasPropertiesWithPrefix(String prefix) {
        for (String key : properties.keySet()) {
            if (key.startsWith(prefix)) {
                return true;
            }
        }
        return false;
    }
}